package com.info.protocol.netty.core.codec;

import com.info.protocol.netty.core.Header;
import com.info.protocol.netty.core.Protocol;
import com.info.protocol.serial.Serializer;
import com.info.protocol.serial.SerializerManager;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class CustomEncoder extends MessageToByteEncoder<Protocol<Object>> {

        /*
        +--------------------------------------------------------------------------------------------+
        |魔数 16bit|协议版本 8bit|序列化方式 8bit|消息长度 32bit |消息类型（请求还是响应）2bit|messageId 64bit |
        +--------------------------------------------------------------------------------------------+
        */

    @Override
    protected void encode(ChannelHandlerContext ctx, Protocol<Object> msg, ByteBuf out) throws Exception {
        log.info("----------------- begin encode -----------------");
        final Header header = msg.getHeader();
        // 写入魔数
        out.writeShort(header.getMagic());
        // 写入使用的协议版本
        out.writeByte(header.getProtocolVersion());
        // 写入序列化方式
        out.writeByte(header.getSerializeType());
        // 对消息内容进行序列化 又因为前面已经实现好了序列化，但是这里只有序列化方式，
        // 我们需要通过这个序列化方式拿到对应的序列化器，因此序列化方式最好有一个管理器，并且提供根据序列化方式
        // 获取具体的序列化器的功能
        Serializer serializer = SerializerManager.getSerializerByCode(header.getSerializeType());
        // 序列化消息
        final Object content = msg.getContent();
        final byte[] data = serializer.serialize(content);
        out.writeInt(data.length);
        // 写入消息类型
        out.writeByte(header.getMessageType());
        // 写入消息id
        out.writeLong(header.getMessageId());
        // 写入消息长度
        // 写入具体的消息内容
        out.writeBytes(data);
    }
}
